<template>
    <el-select v-model="selectValue" v-bind="selectProps" :loading="loading"
               filterable remote :remote-method="remoteMethod"
               @change="handleChange" @visible-change="handleVisibleChange"
               @remove-tag="handleRemoveTag" @clear="handleClear"
               @blur="handleBlur" @focus="handleFocus">
        <el-option v-for="(item, index) in dataList" :key="index"
                   :label="item[optionProps.label]"
                   :value="item[[optionProps.value]]"/>
    </el-select>
</template>

<script>
import { ElSelect } from "../../form/Dynamic/attributes";
export default {
    name: "RemoteSelect",
    model: {
        prop: 'value',
        event: 'changeValue',
    },
    props: {
        value: {
            type: [String, Boolean, Number, Array],
            default: null,
        },
        options: {
            type: Object,
            default() {
                return {
                    init: true,
                };
            },
        },
        disabled: {
            type: Boolean,
            default: false,
        },
        selectFirst: {
            type: Boolean,
            default: false,
        },
        initData: {
            type: Boolean,
            default: true,
        },
    },
    data() {
        return {
            query: '',
            defaultProps: {
                ...ElSelect,
            },
            defaultOptionProps: {
                label: 'label',
                value: 'value',
            },
            dataList: [],
            loading: false,
            selectValue: null,
        };
    },
    computed: {
        selectProps() {
            let props = $.extend({}, this.defaultProps);
            if (this.options) {
                for (let field in this.defaultProps) {
                    if (typeof this.options[field] !== 'undefined') {
                        props[field] = this.options[field];
                    }
                }
            }
            props.disabled = this.disabled;
            delete props.listenerEvent;
            delete props.slots;
            return props;
        },
        optionProps() {
            let props = $.extend({}, this.defaultOptionProps);
            if (this.options && this.options.optionProps) {
                props = $.extend({}, props, this.options.optionProps);
            }
            return props;
        },
    },
    watch: {
        selectValue: {
            handler() {
                this.$emit('changeValue', this.selectValue);
            },
            deep: true,
            immediate: true,
        },
        value: {
            handler() {
                this.selectValue = this.value;
            },
            deep: true,
            immediate: true,
        },
        options: {
            handler() {
                this.init();
            },
            deep: true,
            immediate: true,
        },
    },
    methods: {
        init() {
            const _this = this;
            if (_this.options.init) {
                return;
            }
            _this.selectValue = _this.value;
            if (_this.$utils.isEmpty(_this.options.remote)) {
                console.error('options缺少配置：remote');
                return;
            }
            if (!_this.initData) {
                return;
            }
            this.$nextTick(() => {
                _this.getData(true);
            });
        },
        remoteMethod(query) {
            const _this = this;
            _this.loading = true;
            _this.query = query;
            setTimeout(() => {
                _this.getData();
            }, 500);
        },
        getData(init) {
            const _this = this;
            let queryData = $.extend({}, (_this.options.query || {}));
            queryData.search_value = _this.query;
            queryData.searchValue = _this.query;
            if (init && !_this.selectProps.multiple && _this.$utils.isNotEmpty(_this.selectValue)) {
                queryData.selected_value = _this.selectValue;
            }
            queryData.pageSize = 50;
            return _this.fetchData(_this.options.remote, queryData).then(result => {
                if (typeof _this.options.filterDataList === 'function') {
                    _this.dataList = _this.options.filterDataList(result.data || []);
                } else {
                    _this.dataList = result.data || [];
                }
                _this.loading = false;
                if (!_this.value && _this.selectFirst && _this.$utils.isNotEmptyList(_this.dataList)) {
                    _this.selectValue = _this.dataList[0][_this.optionProps.value];
                }
            }).catch(() => {
            });
        },
        handleChange (value) {
            const _this = this;
            let filter = _this.dataList.filter(item => item[this.optionProps.value] === value);
            this.$emit('event', {
                type: 'change',
                value,
                data: _this.$utils.isNotEmptyList(filter) ? filter[0] : undefined,
            });
        },
        handleVisibleChange (visible) {
            const _this = this;
            _this.$nextTick(() => {
                _this.$emit('event', {
                    type: 'visibleChange',
                    value: visible,
                });
            });
        },
        handleRemoveTag (value) {
            const _this = this;
            _this.$nextTick(() => {
                _this.$emit('event', {
                    type: 'removeTag',
                    value,
                });
            });
        },
        handleClear () {
            const _this = this;
            _this.$nextTick(() => {
                _this.$emit('event', {
                    type: 'clear',
                    value: _this.selectValue,
                });
            });
        },
        handleBlur () {
            const _this = this;
            _this.$nextTick(() => {
                _this.$emit('event', {
                    type: 'blur',
                    value: _this.selectValue,
                });
            });
        },
        handleFocus () {
            const _this = this;
            _this.$nextTick(() => {
                _this.$emit('event', {
                    type: 'focus',
                    value: _this.selectValue,
                });
            });
        },
    },
}
</script>

<style scoped>

</style>
